package com.hex.ds.hdrs.agent.service;

import com.alibaba.fastjson.JSONObject;
import com.hex.bigdata.hbda.base.Page;
import com.hex.ds.hdrs.agent.dao.AgentHeartbeatLogDao;
import com.hex.ds.hdrs.agent.po.AgentConf;
import com.hex.ds.hdrs.agent.po.AgentHeartbeatLog;
import com.hex.ds.hdrs.agent.vo.AgentHeartbeatLogVo;
import com.hex.ds.hdrs.agent.vo.AvgInfoChart;
import com.hex.ds.hdrs.agent.vo.CpuInfoChart;
import com.hex.ds.hdrs.agent.vo.MemoryInfoVo;
import com.hex.ds.hdrs.app.service.IAppAgentRelationService;
import com.hex.ds.hdrs.common.constant.Const;
import com.hex.ds.hdrs.common.utils.BaseUtil;
import com.hex.ds.hdrs.common.utils.HdrsDateUtil;
import com.hex.ds.hdrs.common.utils.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Package: com.hex.ds.hdrs.agent.service
 * @ClassName AgentHeartbeatLogService
 * @Description:agent心跳日志处理层
 * @Author: <gc.zuo>
 * @Date 2021/6/3 15:52
 * @Version v1.0
 **/
@Slf4j
@Service
public class AgentHeartbeatLogService {

    @Autowired
    public AgentHeartbeatLogDao agentHeartbeatLogDao;

    @Autowired
    public IAppAgentRelationService appAgentRelationService;

    @Autowired
    public AgentConfService agentConfService;

    /**
     * 新增
     *
     * @param agentHeartbeatLog
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addLog(AgentHeartbeatLog agentHeartbeatLog) {
        agentHeartbeatLog.setPkId(BaseUtil.getPkId());
        this.agentHeartbeatLogDao.insert(agentHeartbeatLog);
    }

    /**
     * 分页查询
     *
     * @param agentHeartbeatLog
     * @param page
     * @return
     */
    public List<AgentHeartbeatLog> queryHeartbeatLog(AgentHeartbeatLogVo agentHeartbeatLog, Page page) {
        log.debug("【AgentHeartbeatLogService.queryHeartbeatLog】参数agentHeartbeatLog={}", agentHeartbeatLog);
        Map map = MapUtil.Entity2Map(agentHeartbeatLog);
        return agentHeartbeatLogDao.queryHeartbeatLog(map, page);
    }

    /**
     * 查询cpu使用率折线图
     *
     * @param cpuTime
     * @param agentCode
     * @return
     */
    public CpuInfoChart qryCpuChartData(String cpuTime, String agentCode) {

        // 返回给前端的cpu使用率折线图数据格式
        CpuInfoChart cpuInfoChart = new CpuInfoChart();
        // 折线图点数据集合
        List<List<String>> xyInfoList = new ArrayList<>();
        String newTime = "";
        Double d = Double.valueOf(cpuTime);
        if (cpuTime.contains(".")) {
            newTime = HdrsDateUtil.plusHours("0", (int) Math.round(d * 60), "");
        } else {
            newTime = HdrsDateUtil.plusHours("1", d.intValue(), "");
        }

        // 返回cpu数据
        xyInfoList = this.getCpuInfo(agentCode, newTime);
        if (d < Double.valueOf(Const.CPUTIME_CEVTER_NUMBER)) {
            cpuInfoChart.setCpuTimeData(xyInfoList);
            return cpuInfoChart;
        } else {
            cpuInfoChart.setCpuTimeData(this.getAgentResourceData(xyInfoList, cpuTime));
            return cpuInfoChart;
        }
    }

    private List<List<String>> getAgentResourceData(List<List<String>> xyInfoList, String time) {
        try {
            List<List<String>> resList = new ArrayList();
            if (CollectionUtils.isNotEmpty(xyInfoList)) {
                switch (time) {
                    case Const.CHANGE_DATE_HALF_DAY:
                        for (int i = 0; i <= xyInfoList.size(); i = i + Const.HALF_DAY_STEPS) {
                            resList.add(xyInfoList.get(i));
                        }
                        break;
                    case Const.CHANGE_DATE_ONE_DAY:
                        for (int i = 0; i <= xyInfoList.size(); i = i + Const.ONE_DAY_STEPS) {
                            resList.add(xyInfoList.get(i));
                        }
                        break;
                    case Const.CHANGE_DATE_SEVEN_DAY:
                        for (int i = 0; i <= xyInfoList.size(); i = i + Const.SEVEN_DAY_STEPS) {
                            resList.add(xyInfoList.get(i));
                        }
                        break;
                }
            }
            return resList;
        } catch (Exception e) {
            log.error("【AgentHeartbeatLogController.qryCpuInfo】异常：{}", e.getMessage(), e);

            return null;
        }
    }

    /**
     * 查询内存使用率折线图
     *
     * @param ramTime
     * @param agentCode
     * @return
     */
    public CpuInfoChart qryRamChartData(String ramTime, String agentCode) {

        // 返回给前端的内存使用率折线图数据格式
        CpuInfoChart ramInfoChart = new CpuInfoChart();
        // 折线图点数据集合
        List<List<String>> xyInfoList = new ArrayList<>();
        String newTime = "";
        Double d = Double.valueOf(ramTime);
        if (ramTime.contains(".")) {
            newTime = HdrsDateUtil.plusHours("0", (int) Math.round(d * 60), "");
        } else {
            newTime = HdrsDateUtil.plusHours("1", d.intValue(), "");
        }

        // 返回内存数据
        xyInfoList = this.getMemInfo(agentCode, newTime);
        if (d < Double.valueOf(Const.CPUTIME_CEVTER_NUMBER)) {
            ramInfoChart.setMemTimeData(xyInfoList);
            return ramInfoChart;
        } else {
            ramInfoChart.setMemTimeData(this.getAgentResourceData(xyInfoList, ramTime));
            return ramInfoChart;
        }
    }

    /**
     * 查询平均负载折线图
     *
     * @param avgTime
     * @param agentCode
     * @return
     */
    public AvgInfoChart qryAvgChartData(String avgTime, String agentCode) {

        // 返回给前端的平均负载折线图数据格式
        AvgInfoChart avgInfoChart = new AvgInfoChart();
        // 折线图点数据集合
        // 1分钟
        List<List<String>> oneInfoList = new ArrayList<>();
        // 5分钟
        List<List<String>> fifInfoList = new ArrayList<>();
        // 15分钟
        List<List<String>> fifteenInfoList = new ArrayList<>();

        try {
            String nowTime = HdrsDateUtil.getCurTs();
            String aheadTime = "";
            // 获取当前时间推前cpuTime的时间
            if ("0.5".equals(avgTime)) {
                aheadTime = HdrsDateUtil.getAheadTime("0", 30, nowTime);
            } else {
                aheadTime = HdrsDateUtil.getAheadTime("1", Integer.parseInt(avgTime), nowTime);
            }
            // 0.5 1 2 6 12 24 168 720
            if (Double.parseDouble(avgTime) < 6) {
                // 横坐标按每分钟
                while (!aheadTime.equals(nowTime)) {
                    aheadTime = getAvgInfoChart(aheadTime, oneInfoList, fifInfoList, fifteenInfoList, "0", 1,
                            agentCode);
                }

            } else if (Double.parseDouble(avgTime) >= 6 && Double.parseDouble(avgTime) <= 24) {
                // 横坐标按每10分钟
                while (!aheadTime.equals(nowTime)) {
                    aheadTime = getAvgInfoChart(aheadTime, oneInfoList, fifInfoList, fifteenInfoList, "0", 10,
                            agentCode);
                }
            } else if (Double.parseDouble(avgTime) == 168) {
                // 横坐标按每小时
                while (!aheadTime.equals(nowTime)) {
                    aheadTime = getAvgInfoChart(aheadTime, oneInfoList, fifInfoList, fifteenInfoList, "1", 1,
                            agentCode);
                }
            } else {
                // 横坐标按每六时
                while (!aheadTime.equals(nowTime)) {
                    aheadTime = getAvgInfoChart(aheadTime, oneInfoList, fifInfoList, fifteenInfoList, "1", 6,
                            agentCode);
                }
            }
        } catch (Exception e) {
            log.error("查询平均负载率出错: {}", e.getMessage(), e);
        }
        // 返回平均负载数据
        avgInfoChart.setOneMinData(oneInfoList);
        avgInfoChart.setFifMinData(fifInfoList);
        avgInfoChart.setFifteenMinData(fifteenInfoList);
        return avgInfoChart;

    }

    /**
     * 查询磁盘使用率折线图
     *
     * @param fileSysTime
     * @param agentCode
     * @return
     */
    public CpuInfoChart getFileSysInfo(String fileSysTime, String agentCode) {

        // 返回给前端的磁盘使用率折线图数据格式
        CpuInfoChart fileInfoChart = new CpuInfoChart();
        // 折线图点数据集合
        List<List<String>> xyInfoList = new ArrayList<>();
        String newTime = "";
        Double d = Double.valueOf(fileSysTime);
        if (fileSysTime.contains(".")) {
            newTime = HdrsDateUtil.plusHours("0", (int) Math.round(d * 60), "");
        } else {
            newTime = HdrsDateUtil.plusHours("1", d.intValue(), "");
        }

        // 返回内存数据
        xyInfoList = this.getFileInfo(agentCode, newTime);
        if (d < Double.valueOf(Const.CPUTIME_CEVTER_NUMBER)) {
            fileInfoChart.setFileSysData(xyInfoList);
            return fileInfoChart;
        } else {
            fileInfoChart.setFileSysData(this.getAgentResourceData(xyInfoList, fileSysTime));
            return fileInfoChart;
        }
    }

    public List<AgentHeartbeatLog> qryHbLog(Map map) {
        return this.agentHeartbeatLogDao.qryHbLog(map);
    }

    /**
     * 根据不同的时间获取cpuChart数据
     *
     * @param aheadTime
     * @param
     * @param
     * @param
     */
    private String getCpuInfoChart(String aheadTime, List<List<String>> xyInfoList, String type, int diffTime,
                                   String agentCode) {

        AgentHeartbeatLog agentHeartbeatLog = new AgentHeartbeatLog();
        agentHeartbeatLog.setCrtTs(aheadTime);
        agentHeartbeatLog.setAgentCode(agentCode);
        Map map = MapUtil.convertObjToMap(agentHeartbeatLog);
        List<AgentHeartbeatLog> agentHeartbeatLogList = agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (CollectionUtils.isNotEmpty(agentHeartbeatLogList)) {
            // 时间点和cpu信息对应的集合
            List<String> xyInfo = new ArrayList<>();
            xyInfo.add(agentHeartbeatLogList.get(0).getCrtTs());
            xyInfo.add(agentHeartbeatLogList.get(0).getCpuInfo());
            xyInfoList.add(xyInfo);
        }
        // 向后推迟1分钟
        String plusTime = HdrsDateUtil.getPlusTime(type, diffTime, aheadTime);
        return plusTime;
    }

    /**
     * 根据不同的时间获取平均负载数据
     *
     * @param aheadTime
     * @param oneInfoList
     * @param fifInfoList
     * @param fifteenInfoList
     * @param type
     * @param diffTime
     * @return
     */
    private String getAvgInfoChart(String aheadTime, List<List<String>> oneInfoList, List<List<String>> fifInfoList,
                                   List<List<String>> fifteenInfoList, String type, int diffTime, String agentCode) {

        AgentHeartbeatLog agentHeartbeatLog = new AgentHeartbeatLog();
        agentHeartbeatLog.setCrtTs(aheadTime);
        agentHeartbeatLog.setAgentCode(agentCode);
        Map map = MapUtil.convertObjToMap(agentHeartbeatLog);
        List<AgentHeartbeatLog> agentHeartbeatLogList = agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (CollectionUtils.isNotEmpty(agentHeartbeatLogList)) {
            // 时间点和平均负载信息对应的集合
            List<String> onexyInfo = new ArrayList<>();
            List<String> fifxyInfo = new ArrayList<>();
            List<String> fifteenxyInfo = new ArrayList<>();

            String averageLoadInfos = agentHeartbeatLogList.get(0).getAverageLoadInfo();
            String[] avgArr = averageLoadInfos.split(",");
            if (3 == avgArr.length) {
                onexyInfo.add(agentHeartbeatLogList.get(0).getCrtTs());
                onexyInfo.add(avgArr[0]);
                oneInfoList.add(onexyInfo);

                fifxyInfo.add(agentHeartbeatLogList.get(0).getCrtTs());
                fifxyInfo.add(avgArr[1]);
                fifInfoList.add(fifxyInfo);

                fifteenxyInfo.add(agentHeartbeatLogList.get(0).getCrtTs());
                fifteenxyInfo.add(avgArr[2]);
                fifteenInfoList.add(fifteenxyInfo);
            }
        }
        // 向后推迟1分钟
        String plusTime = HdrsDateUtil.getPlusTime(type, diffTime, aheadTime);
        return plusTime;
    }

    /**
     * 根据不同的时间获取内存数据
     *
     * @param aheadTime
     * @param
     * @param
     * @param
     */
    private String getRamInfoChart(String aheadTime, List<List<String>> xyInfoList, String type, int diffTime,
                                   String agentCode) {

        AgentHeartbeatLog agentHeartbeatLog = new AgentHeartbeatLog();
        agentHeartbeatLog.setCrtTs(aheadTime);
        agentHeartbeatLog.setAgentCode(agentCode);
        Map map = MapUtil.convertObjToMap(agentHeartbeatLog);
        List<AgentHeartbeatLog> agentHeartbeatLogList = agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (CollectionUtils.isNotEmpty(agentHeartbeatLogList)) {
            // 时间点和内存信息对应的集合
            List<String> xyInfo = new ArrayList<>();
            xyInfo.add(agentHeartbeatLogList.get(0).getCrtTs());
            xyInfo.add(agentHeartbeatLogList.get(0).getMemoryInfo());
            xyInfoList.add(xyInfo);
        }
        // 向后推迟1分钟
        String plusTime = HdrsDateUtil.getPlusTime(type, diffTime, aheadTime);
        return plusTime;
    }


    public List getAgentHeartList(String appCode, String startTime) {
        log.debug("【agentHeartbeatLogService.getResAndConNumList】appCode: {}", appCode);
        Map map = new HashMap();
        map.put("appCode", appCode);
        map.put("startTime", startTime);
        List resultList = this.agentHeartbeatLogDao.getResAndConnList(map);
        return resultList;
    }

    public List getAgentHeartList2(String appCode, String startTime) {
        log.debug("【agentHeartbeatLogService.getResAndConNumList】appCode: {}", appCode);
        Map map = new HashMap();
        map.put("appCode", appCode);
        map.put("startTime", startTime);
        List resultList = this.agentHeartbeatLogDao.getResAndConnList2(map);
        return resultList;
    }

    /**
     * 查询某节点的磁盘信息
     *
     * @param agentCode
     * @return
     */
    public String qryDicoInfo(String agentCode) {
        AgentHeartbeatLog agentHeartbeatLog = this.qryLastHeartBeat(agentCode);
        if (agentHeartbeatLog != null) {
            return agentHeartbeatLog.getDataJson();
        }
        return null;
    }

    public AgentHeartbeatLog qryLastHeartBeat(String agentCode) {
        return this.agentHeartbeatLogDao.qryLastHeartBeat(agentCode);
    }

    /**
     * 通过agentIp查询心跳日志详细信息
     *
     * @param pkId
     * @return
     */
    public AgentHeartbeatLog getHeartbeatDetail(String pkId) {
        log.info("进入了AgentHeartbeatLogService的getHeartbeatDetail，pkId={}", pkId);
        Map<String, Object> map = new HashMap<>();
        map.put("pkId", pkId);
        AgentHeartbeatLog agentHeartbeatLog = agentHeartbeatLogDao.getHeartbeatDetail(map);
        AgentConf agentConf = this.agentConfService.qryAgentConfByAgentCode(agentHeartbeatLog.getAgentCode());
        agentHeartbeatLog.setAgentName(agentConf.getAgentName());
        return agentHeartbeatLog;
    }

    /**
     * 查询cpu信息
     *
     * @param agentCode
     * @param time
     * @return
     */
    public List<List<String>> getCpuInfo(String agentCode, String time) {
        List<List<String>> resList = new ArrayList();
        List<String> dataList = new ArrayList();
        Map map = new HashMap();
        map.put("agentCode", agentCode);
        map.put("time", time);
        List<AgentHeartbeatLog> list = this.agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (null != list && list.size() > 0) {
            for (AgentHeartbeatLog heartbeatLog : list) {
                List ll = new ArrayList();
                ll.add(heartbeatLog.getCrtTs());
                if (StringUtils.isNotBlank(heartbeatLog.getCpuInfo())) {
                    JSONObject jsonObject = JSONObject.parseObject(heartbeatLog.getCpuInfo());
                    String cpuCombined = jsonObject.getString("cpuCombined");
                    Double a = Double.parseDouble(cpuCombined);
                    BigDecimal bd = new BigDecimal(a);
                    Double d = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    ll.add(String.valueOf(d));
                } else {
                    ll.add("0.00");
                }
                resList.add(ll);
            }
        }
        return resList;
    }

    public List<List<String>> getMemInfo(String agentCode, String time) {
        List<List<String>> resList = new ArrayList();
        Map map = new HashMap();
        map.put("agentCode", agentCode);
        map.put("time", time);
        List<AgentHeartbeatLog> list = this.agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (null != list && list.size() > 0) {
            for (AgentHeartbeatLog heartbeatLog : list) {
                List ll = new ArrayList();
                ll.add(heartbeatLog.getCrtTs());
                if (StringUtils.isNotBlank(heartbeatLog.getMemoryInfo())) {
                    JSONObject jsonObject = JSONObject.parseObject(heartbeatLog.getMemoryInfo());
                    String memUsedRate = jsonObject.getString("memUsedRate");
                    Double a = Double.parseDouble(memUsedRate);
                    BigDecimal bd = new BigDecimal(a);
                    Double d = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    ll.add(String.valueOf(d));
                } else {
                    ll.add("0.00");
                }
                resList.add(ll);
            }
        }
        return resList;
    }


    public List<List<String>> getFileInfo(String agentCode, String time) {
        List<List<String>> resList = new ArrayList();
        Map map = new HashMap();
        map.put("agentCode", agentCode);
        map.put("time", time);
        List<AgentHeartbeatLog> list = this.agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (null != list && list.size() > 0) {
            for (AgentHeartbeatLog heartbeatLog : list) {
                List ll = new ArrayList();
                ll.add(heartbeatLog.getCrtTs());
                if (StringUtils.isNotBlank(heartbeatLog.getFileSysInfo())) {
                    JSONObject jsonObject = JSONObject.parseObject(heartbeatLog.getFileSysInfo());
                    String fileUsedRate = jsonObject.getString("fileUsedRate");
                    Double a = Double.parseDouble(fileUsedRate);
                    BigDecimal bd = new BigDecimal(a);
                    Double d = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    ll.add(String.valueOf(d));
                } else {
                    ll.add("0.00");
                }
                resList.add(ll);
            }
        }
        return resList;
    }

    /**
     * 节点的磁盘信息
     *
     * @param agentCode
     * @return
     */
    public List<MemoryInfoVo> getMemoryObjInfoList(String agentCode) {
        List<MemoryInfoVo> infoVos = new ArrayList<>();
        List<MemoryInfoVo> resInfo = new ArrayList<>();
        Map map = new HashMap();
        map.put("agentCode", agentCode);
        List<AgentHeartbeatLog> list = this.agentHeartbeatLogDao.qryAgentHeartbeatLog(map);
        if (null != list && list.size() > 0) {
            for (AgentHeartbeatLog heartbeatLog : list) {
                String fileSysInfo = heartbeatLog.getFileSysInfo();
                MemoryInfoVo memoryInfoVo = new MemoryInfoVo();
                if (StringUtils.isNotBlank(fileSysInfo)) {
                    JSONObject jsonObject = JSONObject.parseObject(fileSysInfo);
                    memoryInfoVo.setFileDevName(jsonObject.getString("fileDevName"));
                    memoryInfoVo.setFileFree(Long.parseLong(jsonObject.getString("fileFree")));
                    memoryInfoVo.setFileUsed(Long.parseLong(jsonObject.getString("fileUsed")));
                    memoryInfoVo.setFileTotal(Long.parseLong(jsonObject.getString("fileTotal")));
                    memoryInfoVo.setFileUsedRate(Double.parseDouble(jsonObject.getString("fileUsedRate")));
                }
                infoVos.add(memoryInfoVo);
            }
        }
        if (infoVos.size() > 0) {
            resInfo.add(infoVos.get(0));
            return resInfo;
        } else {
            return null;
        }
    }

    /**
     * @Method: delTaskByDate <br>
     * @Param: [map] <br>
     * @Return: void <br>
     * @Description：根据时间删除心跳日志数据<br>
     * @Author： gc.zuo<br>
     * @Date： 2021/6/3 15:53 <br>
     * @Version： V1.0<br>
     */
    public void delTaskByDate(Map map) {
        this.agentHeartbeatLogDao.delTaskByDate(map);
    }

    /**
     * @Method: reductionHeartbeatLogTask <br>
     * @Param: [bitchId] <br>
     * @Return: void <br>
     * @Description：还原心跳日志数据<br>
     * @Author： gc.zuo<br>
     * @Date： 2021/6/3 15:54 <br>
     * @Version： V1.0<br>
     */
    public void reductionHeartbeatLogTask(String bitchId) {
        this.agentHeartbeatLogDao.reductionHeartbeatLogTask(bitchId);
    }

    /**
     * @Method: edit
     * @Param: [agentHeartbeatLog]
     * @Return: void
     * @Description: 修改
     * @Author: ji.tang
     * @Date: 2022/6/14 9:57
     * @Version: V1.0
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void edit(AgentHeartbeatLog agentHeartbeatLog){
        this.agentHeartbeatLogDao.edit(agentHeartbeatLog);
    }
}
